import { ReceptionContext } from '@/components/DataPreview/task';
import FormValidateMessage from '@/components/DataStandard/ReportForm/Viewer/components/formValidateMessage';
import FormItem from '@/components/DataStandard/WorkForm/Viewer/formItem';
import Confirm from '@/executor/open/reconfirm';
import WorkForm from '@/executor/tools/workForm';
import { command } from '@/ts/base';
import { NodeCodeRule, NodeValidateRule, WorkNodeButton } from '@/ts/base/model';
import { NodeType } from '@/ts/base/enum';
import orgCtrl from '@/ts/controller';
import { IWork, IWorkApply, IWorkTask } from '@/ts/core';
import { loadGatewayFields } from '@/utils/work';
import { Button, Input, Modal, Spin, message } from 'antd';
import 'lodash';
import React, {
  ReactElement,
  useContext,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';
import './default.less';
import WorkFormService from '@/ts/scripting/core/services/WorkFormService';
import { IWorkDarft } from '@/ts/core/work/draft';
import { mapErrorToValidateInfo } from '@/ts/scripting/js/util';
import { IReportReception } from '@/ts/core/work/assign/reception/report';
import { delay } from '@/ts/base/common/timer';
import OpenFileDialog from '@/components/OpenFileDialog';
import { SelectBox } from 'devextreme-react';
import { CloseOutlined } from '@ant-design/icons';
import PrintConfigModal from '@/components/Common/FlowDesign/Config/Components/PrintNode/PrintModal';
import { createRoot } from 'react-dom/client';
import PrintTemplate from '@/components/Common/FlowDesign/Config/Components/PrintNode/printTemplate';

// 卡片渲染
interface IProps {
  apply: IWorkApply;
  work: IWork | IWorkTask | IWorkDarft;
  finished?: (success: boolean, instanceId?: string) => void;
  onStagging?: (instanceId: string) => void;
  staggingId?: string;
  content?: string;
  children?: ReactElement;
  splitDetailFormId?: string;
}

/** 办事发起-默认类型 */
const DefaultWayStart: React.FC<IProps> = ({
  apply,
  work,
  finished,
  onStagging,
  staggingId,
  content = '',
  children,
  splitDetailFormId,
}) => {
  const gatewayData = useRef(new Map<string, string[]>());
  const [open, setOpen] = React.useState<boolean>(false);
  const info: { content: string } = { content };
  const gatewayFields = loadGatewayFields(apply.instanceData.node, apply.target);
  const [isModalOpen, setIsModalOpen] = useState(false); //二次确认框
  const [loading, setLoading] = useState(false);
  const [printLoaded, setPrintLoaded] = useState<boolean>(false);
  const [printType, setPrintType] = useState<string>('');
  const [print, setPrint] = useState<any>([]);
  const [printModalCreate, setPrintModalCreate] = useState(false);
  const [resource, setResource] = useState<any>();
  const [ser, setSer] = useState<any>();
  const [printModal, setPrintModal] = useState(false);
  const service = useRef(
    new WorkFormService(apply.target.space, apply.instanceData, true, apply.reception),
  );

  const hasReport = useMemo(
    () => apply.primaryForms.some((f) => f.typeName === '报表'),
    [apply.instanceData.node],
  );

  // 是否为资产合并办事
  const hasMerge = useMemo(
    () =>
      apply.instanceData.node.formRules.filter(
        (i) => i.type === 'combination' && i.applyType === '合并',
      ),
    [apply.instanceData.node],
  );

  // 是否为主子表赋值规则
  const hasAssignment = useMemo(
    () => apply.instanceData.node.formRules.filter((i) => i.type === 'assignment'),
    [apply.instanceData.node],
  );

  const reception = useContext(ReceptionContext);
  const reportStatus = useMemo(() => {
    if (!reception) {
      return null;
    }
    return reception.metadata.content;
  }, [reception]);

  async function handleClick(current: WorkNodeButton) {
    const node = apply.instanceData.node;
    try {
      if (current.type == 'rule') {
        const rule = node.formRules.find((r) => r.id == current.ruleId);
        if (!rule) {
          return;
        }
        if (rule.type == 'code') {
          await service.current.executeCodeRule(rule as NodeCodeRule);
        } else if (rule.type == 'validate') {
          const errors = await service.current.executeValidateRule(
            rule as NodeValidateRule,
          );
          service.current.handlingResult(errors);
        } else {
          console.warn('不支持规则 ' + rule.type);
          return;
        }
      } else {
        message.warn('暂不支持执行器');
      }
    } catch (e) {
      console.error(e);
    }
  }

  const renderNodeButtons = () => {
    const buttons = apply.instanceData.node.buttons || [];
    return buttons.map((button) => {
      return (
        <Button key={button.code} onClick={() => handleClick(button)}>
          {button.name}
        </Button>
      );
    });
  };
  const removePrintIframe = () => {
    const oldIframe = document.getElementById('printedIframe');
    if (oldIframe) {
      oldIframe.remove();
    }
  };
  const handleRemoveItem = (
    e: React.MouseEvent<HTMLSpanElement, MouseEvent>,
    data: { id: string },
  ) => {
    const current = work as IWorkTask;
    e.stopPropagation();
    const newPrintData = print.filter((option: { id: string }) => option.id !== data.id);
    //删除保存
    const parsedResource = JSON.parse(current.instanceData!.node.resource);
    let newAttributes = [...parsedResource.printData.attributes].filter(
      (option: { title: string }) => option.title !== data.id,
    );
    let newPrints = [...parsedResource.print].filter(
      (option: { id: string }) => option.id !== data.id,
    );
    parsedResource.printData.attributes = newAttributes;
    parsedResource.print = newPrints;
    const updatedResourceString = JSON.stringify(parsedResource);
    current.instanceData!.node.resource = updatedResourceString;
    setPrint(newPrintData);
  };
  const saveStatus = useRef<boolean>(false);
  useEffect(() => {
    const current = work as IWorkTask;
    const fetchData = async () => {
      const ser = await service.current;
      const resource = await service.current.model.node.resource;
      setResource(resource ? JSON.parse(resource) : {});
      setSer(ser);

      try {
        let newWork;
        if ((work as IWork).isMyWork) {
          //传入的是Iwork的情况
          newWork = work as IWork;
        } else {
          newWork = (await current.findWorkById(
            apply.metadata.defineId,
          )) as unknown as IWork;
        }

        if (newWork.application.prints.length == 0 && apply.instanceData) {
          newWork.application.prints = JSON.parse(
            apply.instanceData!.node.resource,
          ).print;
        }
        const printsData = await newWork.application.loadAllPrint();
        if (printsData && !printLoaded) {
          printsData.forEach((item: any) => {
            if (apply.instanceData && apply.instanceData.node.print) {
              setPrintType(JSON.parse(apply.instanceData.node.resource).printData.type);
              if (apply.instanceData.node.print.length > 0) {
                apply.instanceData.node.print.forEach((item2: any) => {
                  if (item.id === item2.id) {
                    item2 = item;
                  }
                });
                setPrint(apply.instanceData.node.print);
                setPrintLoaded(true);
              }
            }
          });
        }
      } catch (error) {
        console.error('Error fetching data:', error);
      }
    };
    fetchData();
    saveStatus.current = false;

    const ret = service.current.init();
    if (ret instanceof Error) {
      if (Array.isArray(ret.cause)) {
        service.current.handlingResult(
          ret.cause.map((e) => mapErrorToValidateInfo(e, '初始化')),
        );
      } else {
        service.current.handlingResult([mapErrorToValidateInfo(ret, '初始化')]);
      }
    }
    return () => {
      removePrintIframe();
    };
  }, []);
  return (
    <div className="workstart-default">
      <div className="workstart--toolbar">
        {children} <div style={{ flex: 'auto', width: '1px' }}></div>
        {renderNodeButtons()}
        {printLoaded && !(work as IWorkTask).taskdata && (
          <a
            onClick={() => {
              setPrintModalCreate(true);
            }}>
            添加打印模板
          </a>
        )}
        {!(work as IWorkTask).taskdata && printLoaded && (
          <SelectBox
            showClearButton
            value={printType}
            placeholder="请选择打印模板"
            dataSource={print}
            displayExpr={'name'}
            valueExpr={'id'}
            onFocusIn={() => {
              setPrintType('');
            }}
            onValueChange={(e) => {
              if (!e) return false;
              setPrintType(e);
              //保存
              const parsedResource = JSON.parse(apply.instanceData!.node.resource);
              parsedResource.printData.type = e;
              const updatedResourceString = JSON.stringify(parsedResource);
              apply.instanceData!.node.resource = updatedResourceString;
              const resource = JSON.parse(apply.instanceData?.node.resource ?? '{}');
              setResource(resource);
              setPrintModal(true);
              //e是拿到的id，放到一个数据里，保存掉。然后进入模版页面
            }}
            itemRender={(data) => (
              <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                <span
                  style={{
                    whiteSpace: 'pre-wrap',
                    wordBreak: 'break-all',
                    wordWrap: 'break-word',
                  }}>
                  {data.name}
                </span>
                <CloseOutlined onClick={(e) => handleRemoveItem(e, data)} />
              </div>
            )}
          />
        )}
        {!(work as IWorkTask).taskdata && resource && printLoaded && (
          <Button
            type="primary"
            onClick={() => {
              removePrintIframe();
              const iframe = document.createElement('IFRAME') as HTMLIFrameElement;
              iframe.setAttribute(
                'style',
                'position:fixed;width:100%;height:100%;left:0px;top:0px; z-index: 1000; background: rgba(0, 0, 0, 0); display: none;',
              );
              iframe.setAttribute('id', 'printedIframe');
              iframe.onload = () => {
                let doc = iframe.contentWindow?.document;
                const loading = () => {
                  setTimeout(() => {
                    iframe.contentWindow?.focus();
                    iframe.contentWindow?.print();
                  }, 1000);
                  if (navigator.userAgent.indexOf('MSIE') > 0) {
                    document.body.removeChild(iframe);
                  }
                };
                createRoot(doc as unknown as Element | DocumentFragment).render(
                  <PrintTemplate
                    name={work.name}
                    instanceData={apply.instanceData}
                    printData={resource.printData}
                    print={print}
                    loading={loading}
                    type={'default'}
                  />,
                );
              };
              document.body.appendChild(iframe);
            }}>
            打印
          </Button>
        )}
        {printModalCreate && (
          <OpenFileDialog
            multiple
            title={`选择打印模板`}
            accepts={['打印模板']}
            rootKey={''}
            excludeIds={print.filter((i: any) => i.id).map((file: any) => file.id)}
            onCancel={() => setPrintModalCreate(false)}
            onOk={(files) => {
              //保存到办事上
              setPrint([...print, ...files]);
              //保存
              /* const parsedResource = JSON.parse(current.instanceData!.node.resource);
                let newAttributes = [...parsedResource.printData.attributes];
                let newPrints = [...parsedResource.print];
                files.map((file) => {
                  newAttributes.push({ title: file.id });
                  newPrints.push(file);
                });
                const updatedPrintData = {
                  ...parsedResource.printData,
                  attributes: newAttributes,
                }; */
              setPrintModalCreate(false);
            }}
          />
        )}
        {printModal && (
          <PrintConfigModal
            refresh={(cur) => {
              apply.instanceData!.node.resource = JSON.stringify(cur);
              setPrintModal(false);
            }}
            resource={JSON.parse(apply.instanceData!.node.resource)}
            printType={printType}
            print={print}
            ser={ser}
            primaryForms={apply.instanceData!.node.primaryForms}
            detailForms={apply.instanceData!.node.detailForms}
            type={'default'}
          />
        )}
        {onStagging && (
          <Button
            type="primary"
            style={{ marginLeft: 10 }}
            onClick={async () => {
              if (saveStatus.current) {
                message.warn('请勿重复提交单据！');
                return null;
              }
              saveStatus.current = true;
              const instance = await apply.staggingApply(
                info.content,
                gatewayData.current,
                orgCtrl.user.workStagging,
                staggingId,
              );
              if (instance) {
                orgCtrl.user.workStagging.cache.push(instance);
                onStagging?.apply(this, [instance.id]);
                finished && finished(false);
              } else {
                saveStatus.current = false;
              }
            }}>
            保存草稿
          </Button>
        )}
        {hasReport && reportStatus?.treeNode.nodeType == NodeType.Summary && (
          <Button
            onClick={async () => {
              try {
                setLoading(true);
                const changes = await service.current.summaryAll(
                  reception as IReportReception,
                );
                if (changes.length > 0) {
                  message.success('汇总成功');
                } else {
                  message.success('没有可汇总的数据');
                }
              } catch (error) {
                console.error(error);
                message.error('汇总失败');
              } finally {
                setLoading(false);
              }
            }}>
            汇总
          </Button>
        )}
        {hasReport && (
          <Button
            onClick={async () => {
              try {
                setLoading(true);
                // 等待loading显示出来
                await delay(10);
                await service.current.calculateAll();
                message.success('计算成功');
              } catch (error) {
                console.error(error);
                service.current.handlingResult([mapErrorToValidateInfo(error, '计算')]);
              } finally {
                setLoading(false);
              }
            }}>
            计算
          </Button>
        )}
        {hasReport && (
          <Button
            onClick={async () => {
              const errors = service.current.validateAll();
              if (errors.some((e) => e.errorLevel == 'error')) {
                message.error('校验失败');
              } else if (errors.length > 0) {
                message.warning(`校验通过，但存在 ${errors.length} 个问题，请核实`);
              } else {
                message.success('校验成功');
              }
            }}>
            校验
          </Button>
        )}
        <Button
          type="primary"
          onClick={async () => {
            let errors = service.current.validateAll();
            if (errors.some((e) => e.errorLevel == 'error')) {
              message.error('校验失败');
            } else {
              if (hasAssignment.length > 0) {
                await service.current.assignment();
              }
              if (hasMerge.length > 0) {
                await service.current.assetMerge();
              }
              if (gatewayFields.length > 0) {
                setOpen(true);
              } else {
                setIsModalOpen(true);
              }
            }
          }}>
          提交
        </Button>
        {'taskdata' in work && (
          <Button
            type="link"
            onClick={async () => {
              command.emitter('executor', 'remark', work);
            }}>
            查看任务详情
          </Button>
        )}
      </div>
      <div className="workstart-content">
        <div className="workstart-content-left">
          <FormValidateMessage service={service.current} />
        </div>
        <div className="workstart-content-right">
          {loading && (
            <div className="loading-spin">
              <Spin spinning></Spin>
            </div>
          )}
          <WorkForm
            allowEdit
            belong={apply.target.space}
            data={apply.instanceData}
            nodeId={apply.instanceData.node.id}
            service={service.current}
            splitDetailFormId={splitDetailFormId}
          />
          <div style={{ padding: 10, display: 'flex', alignItems: 'flex-end' }}>
            <Input.TextArea
              style={{ height: 100 }}
              placeholder="请填写备注信息"
              defaultValue={content}
              onChange={(e) => {
                info.content = e.target.value;
              }}
            />
          </div>
        </div>
      </div>
      <Modal
        width={400}
        title="请选择审批人"
        open={open}
        onOk={() => {
          setOpen(false);
          setIsModalOpen(true);
        }}
        onCancel={() => setOpen(false)}>
        {gatewayFields.map((field) => (
          <FormItem
            rules={[]}
            key={field.id}
            data={gatewayData.current}
            numStr={'1'}
            field={field}
            belong={work.directory.target.space}
            onValuesChange={(fieldId, data) => {
              gatewayData.current.set(fieldId, Array.isArray(data) ? data : [data]);
            }}
          />
        ))}
      </Modal>
      {isModalOpen && !saveStatus.current && (
        <Confirm
          open={isModalOpen}
          onCancel={() => setIsModalOpen(false)}
          onOk={async () => {
            if (saveStatus.current) {
              message.warn('请勿重复提交单据！');
              return null;
            }
            saveStatus.current = true;
            setIsModalOpen(false);
            try {
              setLoading(true);
              const instance = await apply.createApply(
                apply.target.spaceId,
                info.content,
                gatewayData.current,
              );
              if (instance) {
                message.success('提交成功');
                finished?.(true, instance.id);
              } else {
                message.warn('提交失败');
                saveStatus.current = false;
              }
            } finally {
              setLoading(false);
            }
          }}
        />
      )}
    </div>
  );
};

export default DefaultWayStart;
